<template>
  <div id="app"></div>
</template>

<script>
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import MapboxLanguage from '@mapbox/mapbox-gl-language';
// import { getHistoryData } from './api/historyData';
import { FPSControl } from 'mapbox-gl-fps/lib/MapboxFPS';

import { RulerControl, ZoomControl } from 'mapbox-gl-controls';

const COLOR_LEVEL = [
  'rgba(0,255,0,0.7)',
  'rgba(255,255,255,0.7)',
  'rgba(255,125,0,0.7)',
  'rgba(255,0,0,0.7)',
  'rgba(152,0,75,0.7)',
  'rgba(178,24,43,0.7)',
];

import 'mapbox-gl-controls/lib/controls.css';

export default {
  data() {
    return {
      // 历史数据
      historyData: null,
      // map 地图对象实例
      map: null,
    };
  },
  beforeCreate() {
    // 兼容旧版本没有remove()的情况
    if (!('remove' in Element.prototype)) {
      Element.prototype.remove = function () {
        if (this.parentNode) {
          this.parentNode.removeChild(this);
        }
      };
    }
  },
  mounted() {
    this._createBaseMap();
  },
  methods: {
    _createBaseMap() {
      mapboxgl.accessToken =
        'pk.eyJ1IjoiaW54bG54IiwiYSI6ImNsMzRmZDE4dTBhOWczaWs3a2psanphMnUifQ.iKIlYhNlW_13OqBJLOc9sw';

      const map = new mapboxgl.Map({
        container: 'app',
        //自己绘制的样式地图令牌
        antialias: true, //抗锯齿
        style: 'mapbox://styles/mapbox/dark-v10',
        center: [113.97923191113188, 22.589860256941634],
        zoom: 12,
      });

      this.map = map;
      window.map = map;
      // 初始化各种控制器插件
      this.initControl(map);

      map.on('load', function () {
        // 添加矢量切片数据源
        map.addSource('custom-vector-source', {
          type: 'vector',
          tileSize: 512,
          scheme: 'tms',
          tiles: [
            'http://localhost:12306/geoserver/gwc/service/tms/1.0.0/cite%3A7wdata@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf',
          ],
        });
        // 添加图层
        map.addLayer({
          id: 'custom-vector-tile-layer',
          type: 'circle',
          source: 'custom-vector-source',
          'source-layer': '7wdata',
          paint: {
            // Size circle radius by earthquake magnitude and zoom level  大小圈半径由 PM2.5 和缩放级别共同决定
            'circle-radius': [
              'interpolate',
              ['linear'],
              ['zoom'],
              9,
              ['interpolate', ['linear'], ['get', 'PM2.5 μg/'], 500, 1],
              10,
              // ['interpolate', ['linear'], ['get', 'mag'], 1, 5, 6, 50],
              ['interpolate', ['linear'], ['get', 'PM2.5 μg/'], 500, 0.5],
              18,
              12,
            ],
            // Color circle by earthquake magnitude  用颜色标出 PM2.5 的污染程度
            'circle-color': [
              'interpolate',
              ['linear'],
              ['get', 'PM2.5 μg/'],
              50,
              COLOR_LEVEL[0],
              100,
              COLOR_LEVEL[1],
              150,
              COLOR_LEVEL[2],
              200,
              COLOR_LEVEL[3],
              300,
              COLOR_LEVEL[4],
              500,
              COLOR_LEVEL[5],
            ],
            'circle-stroke-color': 'transparent',
            'circle-stroke-width': 0, // 圆点的边框大小
            // Transition from heatmap to circle layer by zoom level  通过缩放级别从热图过渡到圆圈层
            'circle-opacity': [
              'interpolate',
              ['linear'],
              ['zoom'],
              // zoom 比9小隐藏
              9,
              0,
              // 否则显示
              10,
              1,
            ],
          },
        });
      });

      // zoom变化时打印zoom值
      map.on('zoom', function (e) {
        console.log('zoom :>> ', e.target.getZoom());
      });

      const that = this;
      // 对地图位置点击事件的响应
      map.on('click', function (e) {
        // 查询在视窗中所有的位置
        const features = map.queryRenderedFeatures(e.point, {
          layers: ['custom-vector-tile-layer'],
        });
        // console.log('features :>> ', features);
        if (features.length) {
          const clickedPoint = features[0];
          console.log('clickedPoint :>> ', clickedPoint);
          window.clickPoint = clickedPoint;
          // 1. 地图重定位
          that.flyToStore(clickedPoint, 17);
          // 2. 关闭其他所有的弹出窗口并显示新的弹出窗口
          that.createPopUp(
            clickedPoint,
            `
          <h3>PM2.5</h3>
          <h4>PM2.5:${clickedPoint.properties['PM2.5 μg/']}</h4>
          `
          );
          // 拿到弹出层的真实 dom
          const popHeaderDom = document.querySelector(
            '.mapboxgl-popup-content h3'
          );
          if (!popHeaderDom) return;
          // 将该点 circle-color 的 rgba 值解构出来
          const { r, g, b, a } = clickedPoint.layer.paint['circle-color'];
          popHeaderDom.style.background = `rgba(${r * 255},${g * 255},${
            b * 255
          },${a})`;
        }
      });

      // let pointID = 0;
      // 给矢量瓦片的点添加 mousemove 事件
      map.on('mousemove', 'custom-vector-tile-layer', (e) => {
        map.getCanvas().style.cursor = 'pointer';
        // 如果没有对应的 features 则什么都不做
        if (e.features.length === 0) return;

        const detailPopups =
          document.getElementsByClassName('custom-click-popup');
        // 如果已经弹出了详细的弹出框，则没必要再弹出hover弹出框
        if (detailPopups[0]) return;

        const hoverPopups =
          document.getElementsByClassName('custom-hover-popup');
        // 之前有弹出框的话则移除
        if (hoverPopups[0]) hoverPopups[0].remove();
        // console.log('e.features :>> ', e.features);
        // console.log('e :>> ', e);
        const currentFeature = e.features[0];
        const PM2D5Val = currentFeature.properties['PM2.5 μg/'];
        // 创建一个hover弹出层
        new mapboxgl.Popup({
          closeButton: false,
          className: 'custom-hover-popup',
        })
          .setLngLat(currentFeature.geometry.coordinates)
          .setHTML(
            `
        <div style="text-align:center;">
          <span>PM2.5: ${PM2D5Val}</span>
        </div>
        `
          )
          .addTo(map);
      });

      // 给矢量瓦片的点添加 mouseleave 事件
      map.on('mouseleave', 'custom-vector-tile-layer', function () {
        map.getCanvas().style.cursor = '';
        const hoverPopups =
          document.getElementsByClassName('custom-hover-popup');
        // 之前有弹出框的话则移除
        if (hoverPopups[0]) hoverPopups[0].remove();
      });
    },

    // 飞向指定的经纬度
    flyToStore(currentFeature, zoom = 15) {
      // 如果当前 zoom 比预设的更大，则不进行缩小
      const currentZoom = this.map.getZoom();
      if (currentZoom > zoom) zoom = currentZoom;
      this.map.flyTo({
        center: currentFeature.geometry.coordinates,
        zoom,
        speed: 1,
      });
    },

    // 创建了一个弹出层
    createPopUp(currentFeature, contentHTML = `<h1>这是一个弹出层</h1>`) {
      const popUps = document.getElementsByClassName('mapboxgl-popup');
      // 我们需要检查并移除已经存在的弹出窗口
      if (popUps[0]) popUps[0].remove();

      new mapboxgl.Popup({ closeButton: true, className: 'custom-click-popup' })
        .setLngLat(currentFeature.geometry.coordinates)
        // .setHTML(
        //   '<h3>PM2.5</h3>' +
        //     '<h4>' +
        //     'PM2.5: ' +
        //     currentFeature.properties['PM2.5'] +
        //     '</h4>'
        // )
        .setHTML(contentHTML)
        .addTo(this.map);
    },

    initControl(mapInstance) {
      // 初始化各种控制器插件
      // 启用右上角的控制按钮，放大，缩小，校正方向
      mapInstance.addControl(new mapboxgl.NavigationControl());
      // 测量标尺控制器 ======================================
      mapInstance.addControl(
        new RulerControl({
          units: 'kilometers',
          labelFormat: (n) => `${n.toFixed(2)} km`,
        }),
        'top-right'
      );
      mapInstance.on('ruler.on', () => console.log('ruler: on'));
      mapInstance.on('ruler.off', () => console.log('ruler: off'));
      // ====================================================
      // 改变zoom值的控件 =====================================
      mapInstance.addControl(new ZoomControl(), 'top-left');
      // ====================================================

      // 汉化插件只能被调用一次
      if (mapboxgl.getRTLTextPluginStatus() === 'unavailable') {
        mapboxgl.setRTLTextPlugin(
          'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js',
          () => {}, // 发生错误时的回调函数
          true // Lazy load the plugin only when text is in arabic
        );
        // 设置为中文语言，热更新情况下失效
        const language = new MapboxLanguage({
          defaultLanguage: 'zh-Hans',
        });
        mapInstance.addControl(language);
      }

      // ====================================================

      // 帧速率以及GPU使用情况
      const fpsControl = new FPSControl();
      mapInstance.addControl(fpsControl, 'bottom-left');
    },
  },
  beforeDestroy() {
    this.map.removeLayer('custom-vector-tile-layer');
    this.map.remove();
    this.map = null;
  },
};
</script>

<style>
body {
  padding: 0;
  margin: 0;
  overflow: hidden;
}
#app {
  position: absolute;
  width: 100%;
  top: 0;
  bottom: 0;
}

/* 将底部的logo和信息声明隐藏 */
.mapboxgl-ctrl-logo {
  display: none !important;
}
.mapboxgl-ctrl-bottom-right {
  display: none !important;
}

/* 弹出层样式 */
.mapboxgl-popup {
  padding-bottom: 5px;
}
/* 控制关闭按钮 */
.mapboxgl-popup-close-button {
  /* display: none; */
}
.mapboxgl-popup-content {
  font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
  padding: 0;
  width: 180px;
}
.mapboxgl-popup-content-wrapper {
  padding: 1%;
}
.mapboxgl-popup-content h3 {
  background: #91c949;
  color: #fff;
  margin: 0;
  display: block;
  padding: 10px;
  border-radius: 3px 3px 0 0;
  font-weight: 700;
  /* margin-top: -15px; */
}
.mapboxgl-popup-content h4 {
  margin: 0;
  display: block;
  padding: 10px;
  font-weight: 400;
}
.mapboxgl-popup-content div {
  padding: 10px;
}
.mapboxgl-container .leaflet-marker-icon {
  cursor: pointer;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-content {
  margin-top: 15px;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip {
  border-bottom-color: #91c949;
}
</style>
